module klang.klang.转换工厂.名称碎裂.Mangler_;
import 全局;
import std.conv: ·to = to;
import ··Klang节点_ = klang.klang.语法节点.Klang节点_;
import klang.编译.核心.核心_: 词典_, 创建数组, 返回零值, 创建词典, 十六进制编码, 从后查找字符索引;
import klang.编译.类型.类型_: 基础符号_ = 符号_;
import klang.编译.语法节点.节点_: 基础节点_ = 节点_;
import klang.klang.语法节点.Klang节点_: 节点_ = Klang节点_, 标识符_ = Klang标识符_;
import klang.klang.类型.klang类型_: 符号_ = Klang符号_, 类型_ = Klang类型_, 签名_ = Klang签名_, KSK, 复合标志_, 类型标志_, 实例化类型_, 符号标志_, 内部符号名_, 字面量值_, 字面量值种类_, 类型映射_, 签名标志_;
import klang.klang.检查.klang检查_: 获取类型Id, 获取节点Id, 获取符号的签名组, typeMangleChar, instantiateType, 跳过只读恒定及共享限定符;
import klang.编译.类型.枚举值.枚举值_: 字符_;
import klang.klang.工具.klang工具_: 获取节点的程序集;
enum MODFlags : uint {
    无_ = 0u,
    const_ = 1u,
    immutable_ = 2u,
    shared_ = 4u,
    xx = 5u
}
class Mangler {
    OutBuffer* buf;
    类型_ rootType;
    词典_!(ulong) types;
    词典_!(ulong) idents;
    this(OutBuffer* _buf, 类型_ rootType = ··null!(类型_)) {
        this.buf = _buf;
        this.rootType = rootType;
        this.types = 创建词典!(ulong)();
        this.idents = 创建词典!(ulong)();
    }
    this() {
        this.buf = new OutBuffer(创建数组!(ubyte)());
        this.types = 创建词典!(ulong)();
        this.idents = 创建词典!(ulong)();
    }
    void writeBackRef(ulong pos) {
        this.buf.writeByte(cast(dchar)'Q');
        ulong base = 26;
        ulong mul = 1;
        while(pos >= mul * base) {
            mul *= base;
        }
        while(mul >= base) {
            ubyte dig = (cast(ubyte)(pos / mul));
            this.buf.writeByte(cast(dchar)'A' + dig);
            pos -= dig * mul;
            mul /= base;
        }
        this.buf.writeByte(cast(dchar)'a' + (cast(ubyte)(pos)));
    }
    bool backrefType(类型_ t) {
        if ((t.标志 & 类型标志_.扩展内置类型_) != 0) {
            return false;
        }
        return this.backrefImpl(this.types, t);
    }
    bool backrefId(标识符_ id) {
        return this.backrefImpl(this.idents, id);
    }
    bool backrefsid(dstring id) {
        return this.backrefImpl(this.idents, id);
    }
    bool backrefImpl(词典_!(ulong) aa, 类型_ key) {
        dstring id = .获取类型文本Id(key);
        if (aa.具有(id)) {
            ulong p = aa.获取(id);
            ulong offset = p - 1;
            this.writeBackRef(this.buf.length() - offset);
            return true;
        }
        ulong n = this.buf.length() + 1;
        aa.p·设置(id, n);
        return false;
    }
    bool backrefImpl(词典_!(ulong) aa, 标识符_ key) {
        dstring id = key.标识符.内容;
        if (aa.具有(id)) {
            ulong p = aa.获取(id);
            ulong offset = p - 1;
            this.writeBackRef(this.buf.length() - offset);
            return true;
        }
        ulong n = this.buf.length() + 1;
        aa.p·设置(id, n);
        return false;
    }
    bool backrefImpl(词典_!(ulong) aa, dstring key) {
        dstring id = key;
        if (aa.具有(id)) {
            ulong p = aa.获取(id);
            ulong offset = p - 1;
            this.writeBackRef(this.buf.length() - offset);
            return true;
        }
        ulong n = this.buf.length() + 1;
        aa.p·设置(id, n);
        return false;
    }
    void mangleType(类型_ t) {
        if (!this.backrefType(t)) {
            this.visit(t);
        }
    }
    void 碎裂变量声明(符号_ s) {
        this.buf.writeByte(cast(dchar)'_');
        this.buf.writeByte(cast(dchar)'D');
        this.mangleParent(s.父符号);
        this.mangleIdentifier(.获取符号名(s));
        if (s.类型 !is ··null!(类型_)) {
            this.visitWithMask(s.类型, MODFlags.无_);
        }
    }
    void 碎裂实例化类型(类型_ s) {
        if ((s.复合标志 & 复合标志_.泛型引用_) != 0) {
        }
        else if ((s.复合标志 & 复合标志_.匿名_) != 0) {
            基础符号_ 储存符号 = s.符号;
            (cast(符号_)(s.符号)).类型 = s;
            this._碎裂匿名类型(s);
            s.符号 = 储存符号;
        }
        else {
            // 无类型形参的
            this.mangleParent(s.符号.父符号);
            this.mangleIdentifier(.获取符号名(s.符号));
        }
    }
    private void _碎裂匿名类型(类型_ s) {
        符号_ 符号 = (cast(符号_)(s.符号));
        this.mangleParent(符号.父符号);
        签名_ 签名 = s.当前需要实例化的签名;
        if ((签名.标志 & 签名标志_.是泛型签名_) != 0) {
            this.buf.writestring((cast(char[])("__T"c)));
            this.mangleIdentifier(.获取符号名(s.符号));
            类型_[] 类型实参 = 签名.类型实参;
            if (类型实参 !is ··null!(类型_[])) {
                foreach (类型_ t; 类型实参) {
                    this.buf.writeByte(cast(dchar)'T');
                    this.visitWithMask(t, MODFlags.无_);
                }
                this.buf.writeByte(cast(dchar)'Z');
            }
        }
        this.mangleIdentifier(.获取符号名(s.符号));
        if ((符号.标志 & 符号标志_.静态_) == 0 && (符号.标志 & (符号标志_.方法_ | 符号标志_.构建_ | 符号标志_.释放_ | 符号标志_.签名_ | 符号标志_.内部声明_)) != 0) {
            this.buf.writeByte(cast(dchar)'M');
        }
        this.mangleFuncType(符号, 签名);
    }
    void mangleParameter(符号_ p) {
        ulong xx = (cast(ulong)(p.标志 & (符号标志_.返回局部引用_)));
        if (xx == 符号标志_.返回局部引用_) {
            this.buf.writestring((cast(char[])("NkMK"c)));
            xx &= ~(cast(ulong)(符号标志_.返回局部引用_));
        }
        else if (xx == 符号标志_.返回引用_) {
            this.buf.writestring((cast(char[])("NkK"c)));
            xx &= ~(cast(ulong)(符号标志_.返回局部引用_));
        }
        else if (xx == 符号标志_.返回局部_) {
            this.buf.writestring((cast(char[])("NkM"c)));
            xx &= ~(cast(ulong)(符号标志_.返回局部引用_));
        }
        if (xx == 符号标志_.局部_) {
            this.buf.writeByte(cast(dchar)'M');
        }
        if (xx == 符号标志_.返回_) {
            this.buf.writestring((cast(char[])("NK"c)));
        }
        if (xx == 符号标志_.引用_) {
            this.buf.writeByte(cast(dchar)'K');
        }
        this.visitWithMask(p.类型, MODFlags.无_);
    }
    void mangleParent(基础符号_ s) {
        if (s.父符号 !is ··null!(基础符号_)) {
            符号_ p = (cast(符号_)(s.父符号));
            类型_ t = (cast(符号_)(s)).类型;
            if ((t.映射 !is ··null!(类型映射_)) && (p.标志 & (符号标志_.对象_ | 符号标志_.结构_ | 符号标志_.类型声明_)) != 0) {
                // 父符号是 泛型 类 结构 或 类型声明;
                // 父的父 是 测试单元或 程序集;
                // 不支持内部类;
                类型_ 父符号的声明类型 = p.声明类型;
                类型_ 声明类型 = 跳过只读恒定及共享限定符(父符号的声明类型);
                类型_ 实例化的父类型 = instantiateType(声明类型, t.映射);
                // 碎裂程序集 或 测试单元及程序集;
                // 测试单元不能嵌套;
                this.mangleParent(p.父符号);
                this.buf.writestring((cast(char[])("__T"c)));
                this.mangleIdentifier(.获取符号名(p));
                if ((实例化的父类型.类型实参 !is ··null!(类型_[])) && 实例化的父类型.类型实参.length > 0) {
                    foreach (类型_ T; 实例化的父类型.类型实参) {
                        this.buf.writeByte(cast(dchar)'T');
                        this.visitWithMask(T, MODFlags.无_);
                    }
                }
                this.buf.writeByte(cast(dchar)'Z');
                return;
            }
            else if ((s.标志 & 符号标志_.内部声明_) != 0) {
                // 父符号可能是泛型的;
                // 父符号是 函数声明;
                this.mangleFunc(p, true);
            }
            else {
                // 父符号不是泛型的
                this.mangleParent(p);
            }
        }
        else if ((s.标志 & 符号标志_.程序集_) != 0) {
            if (s.名称 == "全局"d) {
                return;
            }
            dstring[] names = (cast(符号_)(s)).碎裂名称;
            foreach (dstring str; names) {
                this.mangleIdentifier(str);
            }
            return;
        }
        else if ((s.声明组 !is ··null!(基础节点_[])) && s.声明组.length > 0) {
            基础节点_ 节点 = s.声明组[0].父节点;
            if ((节点 !is ··null!(基础节点_)) && 节点.目标种类 == KSK.测试单元语句) {
                ··Klang节点_.程序声明_ 程序集 = 获取节点的程序集(节点);
                dstring[] names = (cast(符号_)(程序集.符号)).碎裂名称;
                foreach (dstring str; names) {
                    this.mangleIdentifier(str);
                }
                this.mangleIdentifier("unittest_N"d ~ .获取节点文本Id(节点));
                return;
            }
        }
        类型_ t2 = (cast(符号_)(s)).类型;
        if ((t2.复合标志 & 复合标志_.泛型引用_) != 0) {
            this.buf.writestring((cast(char[])("__T"c)));
            this.mangleIdentifier(.获取符号名(s));
            if ((t2.类型实参 !is ··null!(类型_[])) && t2.类型实参.length > 0) {
                foreach (类型_ T2; t2.类型实参) {
                    this.buf.writeByte(cast(dchar)'T');
                    this.visitWithMask(T2, MODFlags.无_);
                }
            }
            this.buf.writeByte(cast(dchar)'Z');
        }
        this.mangleIdentifier(.获取符号名(s));
        return;
    }
    void mangleFunc(符号_ s, bool inParent = false) {
        if ((s.标志 & (符号标志_.方法_ | 符号标志_.构建_ | 符号标志_.释放_ | 符号标志_.内部声明_)) != 0) {
            if ((s.标志 & 符号标志_.静态_) == 0) {
                this.buf.writeByte(cast(dchar)'M');
            }
        }
        if (inParent) {
            this._碎裂匿名类型(s.类型);
        }
        else {
            类型_ t = s.类型;
            this.visitWithMask(t, MODFlags.无_);
        }
    }
    void mangleFuncType(符号_ 符号, 签名_ 签名) {
        类型_ 返回类型 = 签名.返回类型;
        MODFlags tmod = .getMODFlags(返回类型);
        MODFlags smod = .getSymbolMODFlags(符号);
        if (smod != tmod) {
            .MODtoDecoBuffer(this.buf, (cast(uint)(tmod)));
        }
        char mc;
        if (符号.外部修饰符 !is ··null!(··Klang节点_.外部修饰符声明_)) {
            ··Klang节点_.外部修饰符声明_ 外部修饰符 = 符号.外部修饰符;
            switch (外部修饰符.目标种类) {
                case KSK.C_: {
                    mc = cast(char)'U';
                    break;
                }
                case KSK.C加加_: {
                    mc = cast(char)'R';
                    break;
                }
                case KSK.Windows_: {
                    mc = cast(char)'W';
                    break;
                }
                case KSK.Objective_C_: {
                    mc = cast(char)'Y';
                    break;
                }
                default: {
                    mc = cast(char)'F';
                }
            }
        }
        else {
            mc = cast(char)'F';
        }
        .·writeln(""d);
        this.buf.writeByte(mc);
        if ((签名.标志 & 签名标志_.是纯净_) != 0) {
            this.buf.writestring((cast(char[])("Na"c)));
        }
        if ((签名.标志 & 签名标志_.是不抛出_) != 0) {
            this.buf.writestring((cast(char[])("Nb"c)));
        }
        if ((签名.标志 & 签名标志_.是无回收_) != 0) {
            this.buf.writestring((cast(char[])("Ni"c)));
        }
        if ((签名.标志 & 签名标志_.是信任_) != 0) {
            this.buf.writestring((cast(char[])("Ne"c)));
        }
        if ((签名.标志 & 签名标志_.是安全_) != 0) {
            this.buf.writestring((cast(char[])("Nf"c)));
        }
        foreach (符号_ p; 签名.形参声明组) {
            this.mangleParameter(p);
        }
        this.buf.writeByte(cast(dchar)'Z');
        this.visitWithMask(返回类型, MODFlags.无_);
    }
    void mangleIdentifier(dstring id) {
        if (!this.backrefsid(id)) {
            string str = ·to!(string)(id);
            char[] chars = (cast(char[])(str));
            this.toBuffer((cast(char[])(·to!(string)(id))));
        }
    }
    void mangleIdentifier(标识符_ id) {
        if (!this.backrefId(id)) {
            string str = ·to!(string)(id.标识符.内容);
            char[] chars = (cast(char[])(str));
            this.toBuffer(chars);
        }
    }
    void toBuffer(char[] id) {
        this.buf.print(id.length);
        this.buf.writestring(id);
    }
    void visit(类型_ t) {
        if (t.类型 !is ··null!(类型_)) {
            this._visitN(t);
        }
        else {
            this._visitT(t);
        }
    }
    private void _visitT(类型_ t) {
        .tyToDecoBuffer(this.buf, t);
        // 所有包含 符号的类型;
        if ((t.复合标志 & (复合标志_.类_ | 复合标志_.结构_ | 复合标志_.类型_)) != 0) {
            符号_ 符号 = (cast(符号_)(t.符号));
            类型_ 储存类型 = 符号.类型;
            符号.类型 = t;
            this.mangleParent(符号.父符号);
            符号.类型 = 储存类型;
            if ((t.复合标志 & 复合标志_.泛型引用_) != 0) {
                this.buf.writestring((cast(char[])("__T"c)));
                this.mangleIdentifier(.获取符号名(t.符号));
                类型_[] 类型实参 = t.类型实参;
                if (类型实参 !is ··null!(类型_[])) {
                    foreach (类型_ pt; 类型实参) {
                        this.buf.writeByte(cast(dchar)'T');
                        this.visitWithMask(pt, MODFlags.无_);
                    }
                    this.buf.writeByte(cast(dchar)'Z');
                }
            }
            this.mangleIdentifier(.获取符号名(t.符号));
        }
        if ((t.复合标志 & 复合标志_.委托_) != 0) {
            符号_ 符号 = (cast(符号_)(t.符号));
            类型_ 储存类型 = 符号.类型;
            符号.类型 = t;
            this.mangleFuncType(符号, t.当前需要实例化的签名);
            符号.类型 = 储存类型;
        }
    }
    private void _visitN(类型_ t) {
        this._visitT(t);
        if ((t.复合标志 & 复合标志_.数组_) != 0) {
            字面量值_ L = t.长度.值;
            ulong n = L.获取正整数64(字面量值种类_.正整数64_);
            this.buf.print(n);
        }
        // 词典
        // 元组
        // ...
        this.visitWithMask(t.类型, .getMODFlags(t));
    }
    void visitWithMask(类型_ t, MODFlags mod) {
        MODFlags tmod = .getMODFlags(t);
        if (tmod != mod) {
            .MODtoDecoBuffer(this.buf, (cast(uint)(tmod)));
            t = t.类型;
        }
        else if ((t.复合标志 & (复合标志_.只读_ | 复合标志_.恒定_ | 复合标志_.共享_)) != 0) {
            t = t.类型;
        }
        this.mangleType(t);
    }
    dstring outString() {
        ubyte[] chs = this.buf.data[0 .. this.buf.offset];
        dchar[] str = 创建数组!(dchar)();
        foreach (ubyte ch; chs) {
            if (ch > 126 || ch < 32) {
                ubyte a = ch / 16;
                ubyte b = ch % 16;
                .追加!(dchar)(str, 字符_.反斜杠);
                .追加!(dchar)(str, 十六进制编码(a));
                .追加!(dchar)(str, 十六进制编码(b));
            }
            else {
                .追加!(dchar)(str, ch);
            }
        }
        return ·to!(dstring)(str);
    }
}
struct OutBuffer {
    ubyte[] data;
    ulong offset;
    this(ubyte[] d) {
        this.data = d;
        this.offset = 0;
    }
    ulong length() {
        return this.offset;
    }
    void reserve(ulong nbytes) {
        if ((this.data.length - this.offset) < nbytes) {
            size_t size = (cast(size_t)((((this.offset + nbytes) * 3 + 30) / 2) & ~15));
            this.data.length = size;
        }
    }
    void setsize(ulong size) {
        this.offset = size;
    }
    void reset() {
        this.offset = 0;
    }
    void write(void* data, ulong nbytes) {
    }
    void write(void[] buf) {
        this.reserve(buf.length);
        .·memcpy(this.data[this.offset .. $].ptr, buf.ptr, buf.length);
        this.offset += buf.length;
    }
    void write(char[] s) {
        this.write((cast(void[])(s)));
    }
    void write(OutBuffer* _buf) {
        if (_buf !is ··null!(OutBuffer*)) {
            this.reserve(_buf.offset);
            .·memcpy(this.data[this.offset .. $].ptr, _buf.data.ptr, (cast(size_t)(_buf.offset)));
            this.offset += _buf.offset;
        }
    }
    void writeByte(dchar b) {
        this.reserve(1);
        this.data[this.offset] = (cast(ubyte)(b));
        ++this.offset;
    }
    void writeByte(char b) {
        this.reserve(1);
        this.data[this.offset] = (cast(ubyte)(b));
        ++this.offset;
    }
    void writeUTF8(uint b) {
        this.reserve(6);
        if (b <= 127) {
            this.data[this.offset] = (cast(ubyte)(b));
            ++this.offset;
        }
        else if (b <= 2047) {
            this.data[this.offset] = (cast(ubyte)((b >> 6) | 192));
            this.data[this.offset + 1] = (cast(ubyte)((b & 63) | 128));
            this.offset += 2;
        }
        else if (b <= 65535) {
            this.data[this.offset] = (cast(ubyte)((b >> 12) | 224));
            this.data[this.offset + 1] = (cast(ubyte)(((b >> 6) & 63) | 128));
            this.data[this.offset + 2] = (cast(ubyte)((b & 63) | 128));
            this.offset += 3;
        }
        else if (b <= 2097151) {
            this.data[this.offset] = (cast(ubyte)((b >> 18) | 240));
            this.data[this.offset + 1] = (cast(ubyte)(((b >> 12) & 63) | 128));
            this.data[this.offset + 1] = (cast(ubyte)(((b >> 6) & 63) | 128));
            this.data[this.offset + 2] = (cast(ubyte)((b & 63) | 128));
            this.offset += 3;
        }
    }
    void writewchar(uint w) {
        this.reserve(2);
        *(cast(ushort*)((cast(void*)((this.data[0 .. this.offset].ptr))))) = (cast(ushort)(w));
        this.offset += 2;
    }
    void writeUTF16(uint w) {
        this.reserve(4);
        if (w <= 65535) {
            *(cast(ushort*)((cast(void*)((this.data[0 .. this.offset].ptr))))) = (cast(ushort)(w));
            this.offset += 2;
        }
        else if (w <= 1114111) {
            *(cast(ushort*)((cast(void*)((this.data[0 .. this.offset].ptr))))) = (cast(ushort)(w >> 10));
            *(cast(ushort*)((cast(void*)((this.data[0 .. this.offset + 2].ptr))))) = (cast(ushort)(w >> 10));
            this.offset += 4;
        }
    }
    void write4(uint w) {
        this.reserve(4);
        *(cast(uint*)(this.data[this.offset .. $].ptr)) = w;
        this.offset += 4;
    }
    void fill0(size_t nbytes) {
        this.reserve(nbytes);
        .·memset(this.data[this.offset .. $].ptr, 0, nbytes);
        this.offset += nbytes;
    }
    char[] allocate(size_t nbytes) {
        this.reserve(nbytes);
        this.offset += nbytes;
        return cast(char[])(this.data[this.offset - nbytes .. this.offset]);
    }
    void bracket(char le, char ri) {
        this.reserve(2);
        .·memmove(this.data[1 .. $].ptr, this.data.ptr, (cast(size_t)(this.offset)));
        this.data[0] = le;
        this.data[this.offset + 1] = ri;
        this.offset += 2;
    }
    void spread(size_t of, size_t nbytes) {
        this.reserve(nbytes);
        .·memmove(this.data[of + nbytes .. $].ptr, this.data[0 .. of].ptr, (cast(size_t)(this.offset - of)));
        this.offset += nbytes;
    }
    dchar[] opSlice() {
        return (cast(dchar[])(this.data[0 .. this.offset]));
    }
    dchar[] opSlice(size_t l, size_t r) {
        return (cast(dchar[])(this.data[l .. r]));
    }
    char[] extractData() {
        ubyte[] p = this.data;
        this.data = ··null!(ubyte[]);
        this.offset = 0;
        return cast(char[])(p);
    }
    char[] extractSlice(bool nullTerminate = false) {
        ulong L = this.offset;
        if (!nullTerminate) {
            return this.extractData()[0 .. L];
        }
        if (L >= 0 && this.data[L - 1] == 字符_.空字符) {
            return this.extractData()[0 .. L - 1];
        }
        this.writeByte(0);
        return this.extractData()[0 .. L];
    }
    char* peekChars() {
        if (this.offset == 0 || this.data[this.offset - 1] != 字符_.空字符) {
            this.writeByte(0);
            --this.offset;
        }
        return (cast(char[])(this.data)).ptr;
    }
    char[] extractChars() {
        if (this.offset == 0 || this.data[this.offset - 1] != 字符_.空字符) {
            this.writeByte(0);
        }
        return this.extractData();
    }
    void print(ulong u) {
        char[] buf = 创建数组!(char)();
        buf.length = 20;
        this.writestring(.unsignedToTempString(u, buf));
    }
    void writestring(char[] _buf) {
        this.write(cast(void[])(_buf));
    }
}
void MODtoDecoBuffer(OutBuffer* buf, uint mod) {
    switch (mod) {
        case 0: {
            break;
        }
        case 1: {
            buf.writeByte(cast(dchar)'x');
            break;
        }
        case 2: {
            buf.writeByte(cast(dchar)'y');
            break;
        }
        case 4: {
            buf.writeByte(cast(dchar)'O');
            break;
        }
        case 5: {
            buf.writeByte(cast(dchar)'O');
            buf.writeByte(cast(dchar)'x');
            break;
        }
        default: {
            assert(false, "不可及"c);
            break;
        }
    }
}
MODFlags getMODFlags(类型_ t) {
    MODFlags mod = MODFlags.无_;
    if ((t.复合标志 & 复合标志_.只读_) != 0) {
        mod |= MODFlags.const_;
    }
    if ((t.复合标志 & 复合标志_.恒定_) != 0) {
        mod |= MODFlags.immutable_;
    }
    else if ((t.复合标志 & 复合标志_.共享_) != 0) {
        mod |= MODFlags.shared_;
    }
    return mod;
}
MODFlags getSymbolMODFlags(符号_ t) {
    MODFlags mod = MODFlags.无_;
    if ((t.标志 & 符号标志_.只读_) != 0) {
        mod |= MODFlags.const_;
    }
    if ((t.标志 & 符号标志_.恒定_) != 0) {
        mod |= MODFlags.immutable_;
    }
    else if ((t.标志 & 符号标志_.共享_) != 0) {
        mod |= MODFlags.shared_;
    }
    return mod;
}
void tyToDecoBuffer(OutBuffer* _buf, 类型_ t) {
    dchar c = typeMangleChar(t);
    _buf.writeByte(c);
    if (c == cast(dchar)'z') {
        _buf.writeByte(cast(dchar)'k');
    }
}
dstring 获取类型文本Id(类型_ t) {
    return ·to!(dstring)(获取类型Id(t));
}
dstring 获取节点文本Id(基础节点_ t) {
    return ·to!(dstring)(获取节点Id(t));
}
char[] unsignedToTempString(ulong value, char[] buf, uint radix = 10) {
    size_t i = buf.length;
    bool 第一层 = true;
    while(第一层 || value > 0) {
        第一层 = false;
        if (value < radix) {
            ubyte x = (cast(ubyte)(value));
            buf[--i] = (cast(char)((x < 10) ? x + cast(dchar)'0' : x - 10 + cast(dchar)'a'));
            break;
        }
        else {
            ubyte x = (cast(ubyte)(value % radix));
            value = value / radix;
            buf[--i] = (cast(char)((x < 10) ? x + cast(dchar)'0' : x - 10 + cast(dchar)'a'));
        }
    }
    return buf[i .. $];
}
dstring 获取符号名(基础符号_ s) {
    if (s.名称 == 内部符号名_.新建_) {
        return "__ctor"d;
    }
    else if (s.名称 == 内部符号名_.释放_) {
        return "__dtor"d;
    }
    else if (s.名称 == 内部符号名_.索引_) {
        // 不支持
        return "__opI"d;
    }
    else if (s.名称 == 内部符号名_.运算符_) {
        // 不支持
        return "__op"d;
    }
    long i = 从后查找字符索引(s.名称, cast(dchar)'|');
    if (i != -1) {
        return s.名称[i .. $];
    }
    return s.名称;
}
